/**
 * @file ui_events.c
 * @brief 电影票务系统UI事件处理模块
 * @details 负责处理用户交互、数据加载、状态更新等核心业务逻辑
 * @author SquareLine Studio
 * @version 1.0
 * @date 2024
 * 
 * 功能模块：
 * 1. 用户认证（登录/注册）
 * 2. 电影详情展示
 * 3. 座位选择与购票
 * 4. 实时数据更新（时间/天气）
 * 5. 错误处理与提示
 */
// Project name: tickets

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <stdbool.h>
#include <unistd.h>
#include "ui.h"
#include "ui_events.h"

#include "./data/userdata.h"
#include "./data/filmdata.h"
#include "./data/seatsdeatil.h"

// ========================== 全局变量定义 ==========================

static char current_username[50]   = "";    /**< 当前登录用户名 */
static char current_film_name[100] = "";    /**< 当前选中电影名 */
static char selected_seats[200]    = "";    /**< 已选座位列表字符串 */
static char selected_time[50]      = "";    /**< 选中的场次时间 */
static int ticket_price            = 0;     /**< 当前电影票价 */
static int selected_seat_count     = 0;     /**< 已选座位数量 */

// 座位复选框对象数组（运行时动态绑定）
#define MAX_SEATS 15
static lv_obj_t* seat_checkboxes[MAX_SEATS]; /**< 座位复选框控件数组 */

// 座位名称映射表（与UI设计保持一致）
static const char* seat_names[] = {
    "C5", "C4", "C3", "C2", "C1",    /**< 第三排座位 */
    "B5", "B4", "B3", "B2", "B1",    /**< 第二排座位 */
    "A5", "A4", "A3", "A2", "A1"     /**< 第一排座位 */
};

// ========================== 静态函数声明 ==========================

// 定时器回调函数
static void hide_popup_timer(lv_timer_t* timer);
static void login_success_timer(lv_timer_t* timer);
static void register_success_timer(lv_timer_t* timer);
static void order_process_timer(lv_timer_t* timer);
static void ticket_success_timer(lv_timer_t* timer);

// 时间更新相关
static void update_time_periodic(lv_timer_t* timer);
static void update_time_display(void);

// 电影详情加载
static void set_movie_details(const char* title, const char* genre, const char* director, const char* writer,
                              const char* year, const char* cast, const char* price);

// 座位管理相关
static bool is_seat_occupied(const char* seat);
static void remove_seat_from_list(const char* seat);
static void clear_selected_seats(void);
static void update_seat_display(void);

// UI辅助函数
static void show_ticket_error(const char* message);
static void show_ticket_success(const char* message);
static void show_loading_error(const char* message);
static void show_loading_panel(void);

// 工具函数
extern void trim_string(char* str);
extern int file_exists(const char* filename);

// ========================== 初始化函数 ==========================

/**
 * @brief 初始化座位复选框数组
 * @details 将UI中的复选框对象映射到数组，方便批量操作
 * @note 必须与SquareLine Studio中的对象名保持一致
 */
static void init_seat_checkboxes(void)
{
    seat_checkboxes[0]  = ui_seat1;
    seat_checkboxes[1]  = ui_seat2;
    seat_checkboxes[2]  = ui_seat3;
    seat_checkboxes[3]  = ui_seat4;
    seat_checkboxes[4]  = ui_seat5;
    seat_checkboxes[5]  = ui_seat6;
    seat_checkboxes[6]  = ui_seat7;
    seat_checkboxes[7]  = ui_seat8;
    seat_checkboxes[8]  = ui_seat9;
    seat_checkboxes[9]  = ui_seat10;
    seat_checkboxes[10] = ui_seat11;
    seat_checkboxes[11] = ui_seat12;
    seat_checkboxes[12] = ui_seat13;
    seat_checkboxes[13] = ui_seat14;
    seat_checkboxes[14] = ui_seat15;
}

// ========================== 工具函数实现 ==========================

/**
 * @brief 去除字符串首尾空白字符
 * @param str 待处理的字符串（会原地修改）
 * @warning 会直接修改传入的字符串
 */
void trim_string(char* str)
{
    if(str == NULL) return;
    
    // 去除前导空格
    char* p = str;
    while(isspace((unsigned char)*p)) p++;
    if(p != str) memmove(str, p, strlen(p) + 1);

    // 去除尾部空格
    char* end = str + strlen(str) - 1;
    while(end >= str && isspace((unsigned char)*end)) {
        *end = '\0';
        end--;
    }
}

/**
 * @brief 检查文件是否存在
 * @param filename 文件路径
 * @return 1-存在，0-不存在
 */
int file_exists(const char* filename)
{
    FILE* file = fopen(filename, "r");
    if(file) {
        fclose(file);
        return 1;
    }
    return 0;
}

/**
 * @brief 安全获取对象的标签文本
 * @param obj LVGL对象
 * @return 文本内容（空字符串表示获取失败）
 * @note 兼容复选框和其他控件类型
 */
static const char* get_obj_label_text_safe(lv_obj_t* obj)
{
    if(obj == NULL) return "";
    
    // 优先使用复选框专用API
    const char* txt = lv_checkbox_get_text(obj);
    if(txt == NULL || strlen(txt) == 0) {
        // 降级使用子对象标签
        lv_obj_t* child = lv_obj_get_child(obj, 0);
        if(child != NULL) {
            txt = lv_label_get_text(child);
            if(txt != NULL) return txt;
        }
        return "";
    }
    return txt;
}

// ========================== 用户认证模块 ==========================

/**
 * @brief 用户登录验证
 * @param e LVGL事件对象
 * @details 验证用户名密码，成功后清空之前用户的购票状态
 */
void login_check(lv_event_t* e)
{
    const char* user   = lv_textarea_get_text(ui_lusertext);
    const char* passwd = lv_textarea_get_text(ui_lpasswdtext);

    if(user == NULL) user = "";
    if(passwd == NULL) passwd = "";

    // 输入验证
    if(strlen(user) == 0 || strlen(passwd) == 0) {
        lv_obj_clear_flag(ui_LuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_lwarncentent, "用户名或密码不能为空");
        lv_timer_t* timer = lv_timer_create(hide_popup_timer, 1000, ui_LuserPopup);
        lv_timer_set_repeat_count(timer, 1);
        return;
    }

    // 读取用户数据文件
    FILE* file = fopen(USERDATA_FILE, "r");
    if(!file) {
        lv_obj_clear_flag(ui_LuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_lwarncentent, "用户数据文件不存在");
        lv_timer_t* timer = lv_timer_create(hide_popup_timer, 1000, ui_LuserPopup);
        lv_timer_set_repeat_count(timer, 1);
        return;
    }

    char line[256];
    int user_found    = 0;
    int login_success = 0;

    // 逐行验证用户信息
    while(fgets(line, sizeof(line), file)) {
        char stored_user[50] = {0}, stored_pass[50] = {0};
        if(sscanf(line, "用户名:%49[^,],密码:%49s", stored_user, stored_pass) == 2) {
            trim_string(stored_user);
            trim_string(stored_pass);

            if(strcmp(stored_user, user) == 0) {
                user_found = 1;
                if(strcmp(stored_pass, passwd) == 0) {
                    login_success = 1;
                    strncpy(current_username, user, sizeof(current_username) - 1);
                    break;
                }
            }
        }
    }
    fclose(file);

    // 处理验证结果
    if(!user_found) {
        lv_obj_clear_flag(ui_LuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_lwarncentent, "不存在的用户");
    } else if(!login_success) {
        lv_obj_clear_flag(ui_LuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_lwarncentent, "密码错误");
    } else {
        // 登录成功后清理环境
        clear_selected_seats();
        
        lv_obj_clear_flag(ui_LuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_lwarncentent, "登录成功");
        lv_timer_t* timer = lv_timer_create(login_success_timer, 3000, NULL);
        lv_timer_set_repeat_count(timer, 1);
    }
}

/**
 * @brief 用户注册处理
 * @param e LVGL事件对象
 * @details 检查用户名唯一性，成功后自动登录
 */
void register_check(lv_event_t* e)
{
    const char* user   = lv_textarea_get_text(ui_rusertext);
    const char* passwd = lv_textarea_get_text(ui_rpasswdtext);

    if(user == NULL) user = "";
    if(passwd == NULL) passwd = "";

    // 输入长度验证
    if(strlen(user) < 6 || strlen(user) > 18 || strlen(passwd) < 6 || strlen(passwd) > 18) {
        lv_obj_clear_flag(ui_RuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_rwarncentent, "用户名和密码长度需在6-18之间");
        lv_timer_t* timer = lv_timer_create(hide_popup_timer, 1000, ui_RuserPopup);
        lv_timer_set_repeat_count(timer, 1);
        return;
    }

    // 检查用户是否存在
    FILE* file = fopen(USERDATA_FILE, "r");
    if(file) {
        char line[256];
        while(fgets(line, sizeof(line), file)) {
            char stored_user[50] = {0};
            if(sscanf(line, "用户名:%49[^,]", stored_user) == 1) {
                trim_string(stored_user);
                if(strcmp(stored_user, user) == 0) {
                    fclose(file);
                    lv_obj_clear_flag(ui_RuserPopup, LV_OBJ_FLAG_HIDDEN);
                    lv_label_set_text(ui_rwarncentent, "用户已存在");
                    lv_timer_t* timer = lv_timer_create(hide_popup_timer, 1000, ui_RuserPopup);
                    lv_timer_set_repeat_count(timer, 1);
                    return;
                }
            }
        }
        fclose(file);
    }

    // 写入新用户数据
    file = fopen(USERDATA_FILE, "a");
    if(file) {
        fprintf(file, "用户名:%s,密码:%s\n", user, passwd);
        fclose(file);

        // 自动登录并清理环境
        strncpy(current_username, user, sizeof(current_username) - 1);
        clear_selected_seats();

        lv_obj_clear_flag(ui_RuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_rwarncentent, "注册成功");
        lv_timer_t* timer = lv_timer_create(register_success_timer, 3000, NULL);
        lv_timer_set_repeat_count(timer, 1);
    } else {
        lv_obj_clear_flag(ui_RuserPopup, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_rwarncentent, "注册失败：文件写入错误");
        lv_timer_t* timer = lv_timer_create(hide_popup_timer, 1000, ui_RuserPopup);
        lv_timer_set_repeat_count(timer, 1);
    }
}

// ========================== 主界面时间模块 ==========================

/**
 * @brief 主界面初始化
 * @param e LVGL事件对象
 * @details 设置当前用户信息、天气、时间，并启动定时器
 */
void tickScre_Init(lv_event_t* e)
{
    // 显示当前用户
    lv_label_set_text_fmt(ui_currentuserlabel, "当前用户: %s", 
                         strlen(current_username) > 0 ? current_username : "未登录");

    // 设置天气信息（可扩展为网络获取）
    lv_label_set_text(ui_weather, "天气: 晴 25度");

    // 清理座位选择状态
    clear_selected_seats();

    // 启动时间更新
    update_time_display();
    lv_timer_create(update_time_periodic, 1000, NULL);  // 每秒更新
}

/**
 * @brief 时间更新定时器回调
 * @param timer LVGL定时器对象
 */
static void update_time_periodic(lv_timer_t* timer)
{
    (void)timer;  // 避免未使用警告
    update_time_display();
}

/**
 * @brief 更新主界面时间显示
 * @details 显示格式：2024年12月20日 周五 14:30:25
 */
static void update_time_display()
{
    time_t now    = time(NULL);
    struct tm* t  = localtime(&now);
    if(t == NULL) return;

    const char* weekdays[] = {"日", "一", "二", "三", "四", "五", "六"};
    lv_label_set_text_fmt(ui_time, "时间: %04d年%02d月%02d日 周%s %02d:%02d:%02d", 
                         t->tm_year + 1900, t->tm_mon + 1,
                         t->tm_mday, weekdays[t->tm_wday], 
                         t->tm_hour, t->tm_min, t->tm_sec);
}

// ========================== 电影日期标签处理 ==========================

/**
 * @brief 电影日期排序处理
 * @param e LVGL事件对象
 * @details 根据当前日期动态生成标签文本，修复日期格式和越界问题
 */
void Date_Sort(lv_event_t* e)
{
    time_t now = time(NULL);
    struct tm* t = localtime(&now);
    char buf[32];

    if(t == NULL || ui_TabView1 == NULL) return;

    // 生成今日标签 - 使用两位数格式，避免单位数月份/日期显示不整齐
    sprintf(buf, "今天(%02d月/%02d日)", t->tm_mon + 1, t->tm_mday);
    lv_tabview_rename_tab(ui_TabView1, 0, buf);

    // 生成明日标签 - 使用临时结构体避免修改原始时间
    struct tm tomorrow = *t;
    tomorrow.tm_mday += 1;
    tomorrow.tm_hour = 12;  // 设置为中午避免时区问题
    mktime(&tomorrow);  // 标准化日期，自动处理月份和年份进位
    sprintf(buf, "明天(%02d月/%02d日)", tomorrow.tm_mon + 1, tomorrow.tm_mday);
    lv_tabview_rename_tab(ui_TabView1, 1, buf);

    // 生成后天标签
    struct tm after_tomorrow = *t;
    after_tomorrow.tm_mday += 2;
    after_tomorrow.tm_hour = 12;
    mktime(&after_tomorrow);
    sprintf(buf, "后天(%02d月/%02d日)", after_tomorrow.tm_mon + 1, after_tomorrow.tm_mday);
    lv_tabview_rename_tab(ui_TabView1, 2, buf);

    // 生成三天后标签
    struct tm three_days = *t;
    three_days.tm_mday += 3;
    three_days.tm_hour = 12;
    mktime(&three_days);
    sprintf(buf, "两天后(%02d月/%02d日)", three_days.tm_mon + 1, three_days.tm_mday);
    lv_tabview_rename_tab(ui_TabView1, 3, buf);

    // 生成四天后标签
    struct tm four_days = *t;
    four_days.tm_mday += 4;
    four_days.tm_hour = 12;
    mktime(&four_days);
    sprintf(buf, "三天后(%02d月/%02d日)", four_days.tm_mon + 1, four_days.tm_mday);
    lv_tabview_rename_tab(ui_TabView1, 4, buf);
}


// ---------------- 电影详情 ----------------
void update_filminfo(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    if(target == NULL) return;

    // 取第一个子 label 作为电影名（SquareLine 通常把文本放在子 label）
    lv_obj_t * child       = lv_obj_get_child(target, 0);
    const char * film_name = (child ? lv_label_get_text(child) : "");
    if(film_name == NULL) film_name = "";

    strncpy(current_film_name, film_name, sizeof(current_film_name) - 1);

    FILE * file = fopen(FILMDATA_FILE, "r");
    if(!file) {
        set_movie_details("NONE", "NONE", "NONE", "NONE", "NONE", "NONE", "0");
        return;
    }

    char line[512];
    int found = 0;

    while(fgets(line, sizeof(line), file)) {
        if(strstr(line, film_name)) {
            char title[100] = {0}, genre[100] = {0}, director[100] = {0}, writer[100] = {0}, year[50] = {0},
                 cast[200] = {0}, price[20] = {0};

            if(sscanf(line, "片名:%99[^,],类型:%99[^,],导演:%99[^,],编剧:%99[^,],年份:%49[^,],主演:%199[^,],票价:%19s",
                      title, genre, director, writer, year, cast, price) == 7) {
                set_movie_details(title, genre, director, writer, year, cast, price);
                found = 1;
                break;
            }
        }
    }
    fclose(file);

    if(!found) {
        set_movie_details("NONE", "NONE", "NONE", "NONE", "NONE", "NONE", "0");
    }
    /* 同步到购票界面的电影名（如果购票界面/标签已创建就更新） */
    if (ui_filmtitle) lv_label_set_text_fmt(ui_filmtitle, "电影片名: %s", current_film_name);
}

static void set_movie_details(const char * title, const char * genre, const char * director, const char * writer,
                              const char * year, const char * cast, const char * price)
{
    lv_label_set_text_fmt(ui_title, "片名: %s", title);
    lv_label_set_text_fmt(ui_genre, "类型: %s", genre);
    lv_label_set_text_fmt(ui_director, "导演: %s", director);
    lv_label_set_text_fmt(ui_writer, "编剧: %s", writer);
    lv_label_set_text_fmt(ui_releasedate, "年份: %s", year);
    lv_label_set_text_fmt(ui_cast, "主演: %s", cast);

    // 票价解析：兼容 "$99" 或 "99"
    if(price == NULL || price[0] == '\0' || strcmp(price, "0") == 0) {
        ticket_price = 0;
    } else if(price[0] == '$') {
        ticket_price = atoi(price + 1);
    } else {
        ticket_price = atoi(price);
    }
}

// ---------------- 选座 ----------------
void Change_Seat(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    if(target == NULL) {
        printf("Change_Seat: target is NULL\n");
        return;
    }

    bool checked = lv_obj_has_state(target, LV_STATE_CHECKED);

    // 安全获取座位文本
    const char * seat_text = get_obj_label_text_safe(target);
    
    // 调试信息：打印获取到的座位文本
    printf("Change_Seat: get_obj_label_text_safe returned: '%s' (length: %d)\n", 
           seat_text ? seat_text : "NULL", seat_text ? (int)strlen(seat_text) : 0);
    
    // 检查座位文本是否有效
    if(seat_text == NULL || strlen(seat_text) == 0) {
        printf("Change_Seat: seat_text is empty\n");
        return;
    }

    // 检查座位是否已被购买
    if(checked) {
        bool occupied = is_seat_occupied(seat_text);
        printf("Change_Seat: checking if seat %s is occupied: %s\n", seat_text, occupied ? "YES" : "NO");
        
        if(occupied) {
            // 取消选中
            lv_obj_clear_state(target, LV_STATE_CHECKED);
            printf("Change_Seat: seat %s is already occupied, clearing selection\n", seat_text);
            return;
        }
    }

    if(checked) {
        selected_seat_count++;
        if(strlen(selected_seats) > 0) strcat(selected_seats, " ");
        strncat(selected_seats, seat_text, sizeof(selected_seats) - strlen(selected_seats) - 1);
        printf("Change_Seat: added seat %s, total seats: %d, selected_seats: '%s'\n", 
               seat_text, selected_seat_count, selected_seats);
    } else {
        if(selected_seat_count > 0) selected_seat_count--;
        remove_seat_from_list(seat_text);
        printf("Change_Seat: removed seat %s, total seats: %d, selected_seats: '%s'\n", 
               seat_text, selected_seat_count, selected_seats);
    }

    // 确保ticket_price有有效值
    if (ticket_price <= 0) {
        printf("Warning: ticket_price is %d (invalid), setting to default 50\n", ticket_price);
        ticket_price = 50; // 设置默认票价
    }

    // 强制更新显示，不依赖条件检查
    if (ui_postion) {
        if (strlen(selected_seats) > 0) {
            // 添加换行符到座位号文本中，每3个座位后换行，避免文本过长
            char formatted_seats[256] = {0};
            char seats_copy[256] = {0};  // 创建原始字符串的副本
            strncpy(seats_copy, selected_seats, sizeof(seats_copy) - 1);
            
            char *token = strtok(seats_copy, " ");  // 对副本进行解析，避免修改原始数据
            int seat_count = 0;
            
            while (token != NULL) {
                if (seat_count > 0) {
                    if (seat_count % 3 == 0) {
                        strcat(formatted_seats, "\n");  // 每3个座位换行
                    } else {
                        strcat(formatted_seats, " ");   // 否则添加空格
                    }
                }
                strncat(formatted_seats, token, sizeof(formatted_seats) - strlen(formatted_seats) - 1);
                seat_count++;
                token = strtok(NULL, " ");
            }
            
            lv_label_set_text_fmt(ui_postion, "座位号:\n%s", formatted_seats);
        } else {
            lv_label_set_text(ui_postion, "座位号:");
        }
        
        printf("Change_Seat: updated ui_postion with seats: '%s'\n", selected_seats);
        // 刷新UI以确保立即显示更新
        lv_obj_refresh_ext_draw_size(ui_postion);
        lv_obj_invalidate(ui_postion);
    } else {
        printf("Change_Seat: ui_postion is NULL\n");
    }

    // 更新总票价
    if (ui_money) {
        int total_price = selected_seat_count * ticket_price;
        lv_label_set_text_fmt(ui_money, "票价(%d元/张): 总计%d元", ticket_price, total_price);
        printf("Change_Seat: updated ui_money with total price: %d\n", total_price);
        // 刷新UI以确保立即显示更新
        lv_obj_refresh_ext_draw_size(ui_money);
        lv_obj_invalidate(ui_money);
    } else {
        printf("Change_Seat: ui_money is NULL\n");
    }

    // 确保调用原有的更新函数
    update_seat_display();
}

static bool is_seat_occupied(const char * seat)
{
    if(seat == NULL || seat[0] == '\0') return false;
    if(!file_exists(SEATS_FILE)) return false;

    FILE * file = fopen(SEATS_FILE, "r");
    if(!file) return false;

    char line[512];
    bool occupied         = false;
    time_t now            = time(NULL);
    struct tm * t         = localtime(&now);
    char current_date[32] = {0};
    if(t) snprintf(current_date, sizeof(current_date), "%d年%d月%d日", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);

    while(fgets(line, sizeof(line), file)) {
        // 检查电影、日期、场次和座位是否已被任何用户购买
        // 不区分用户，只要是相同的电影+日期+场次+座位，就是已占用
        if(strstr(line, current_film_name) && 
           strstr(line, current_date) && 
           strstr(line, selected_time) &&
           strstr(line, seat)) {
            occupied = true;
            break;
        }
    }
    fclose(file);
    return occupied;
}

static void remove_seat_from_list(const char * seat)
{
    if(seat == NULL || seat[0] == '\0') return;

    char temp[200] = "";
    char buf[200];
    strncpy(buf, selected_seats, sizeof(buf) - 1);
    buf[sizeof(buf) - 1] = '\0';

    char * token = strtok(buf, " ");
    while(token) {
        if(strcmp(token, seat) != 0) {
            if(strlen(temp) > 0) strcat(temp, " ");
            strcat(temp, token);
        }
        token = strtok(NULL, " ");
    }
    strncpy(selected_seats, temp, sizeof(selected_seats) - 1);
    selected_seats[sizeof(selected_seats) - 1] = '\0';
}

static void clear_selected_seats(void)
{
    selected_seats[0] = '\0';
    selected_seat_count = 0;
    
    // 取消所有复选框的选中状态
    for(int i = 0; i < MAX_SEATS; i++) {
        if(seat_checkboxes[i] != NULL) {
            lv_obj_clear_state(seat_checkboxes[i], LV_STATE_CHECKED);
        }
    }
    
    update_seat_display();
}

static void reset_time_selection(void)
{
    // 重置场次选择为第一个选项
    if(ui_picktime) {
        lv_dropdown_set_selected(ui_picktime, 0);
        lv_dropdown_get_selected_str(ui_picktime, selected_time, sizeof(selected_time));
    }
}

static void update_seat_display(void)
{
    // 更新右侧座位号 - 确保总是更新，不依赖条件检查
    if (ui_postion)
        lv_label_set_text_fmt(ui_postion, "座位号: %s", selected_seats);
    else {
        // 调试信息，帮助定位问题
        printf("Warning: ui_postion is NULL, cannot update seat display\n");
    }

    // 更新总票价 - 确保总是更新，不依赖条件检查
    int total_price = selected_seat_count * ticket_price;
    if (ui_money)
        lv_label_set_text_fmt(ui_money, "票价(%d元/张): 总计%d元", ticket_price, total_price);
    else {
        // 调试信息，帮助定位问题
        printf("Warning: ui_money is NULL, cannot update price display\n");
    }
}

// 显示加载面板（用于正常流程）
static void show_loading_panel(void)
{
    if(ui_blackpanel) {
        // 更新加载面板的提示文本，确保不会显示之前的错误消息
        if(ui_tip) {
            lv_label_set_text(ui_tip, "正在处理订单...");
        }
        
        // 设置为模态对话框，阻止其他操作
        lv_obj_clear_flag(ui_blackpanel, LV_OBJ_FLAG_HIDDEN);
        
        // 设置面板为可点击，阻止事件穿透到下层控件
        lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_CLICKABLE);
        lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_CLICK_FOCUSABLE);
        
        // 设置面板背景为半透明黑色，覆盖整个屏幕
        lv_obj_set_size(ui_blackpanel, LV_PCT(100), LV_PCT(100));
        lv_obj_center(ui_blackpanel);
        lv_obj_set_style_bg_color(ui_blackpanel, lv_color_black(), LV_PART_MAIN);
        lv_obj_set_style_bg_opa(ui_blackpanel, LV_OPA_70, LV_PART_MAIN);  // 70%透明度
        
        // 确保加载面板在最上层
        lv_obj_move_foreground(ui_blackpanel);
    }
}

// ---------------- 订单 ----------------
void Order_Process(lv_event_t * e)
{
    (void)e;
    // 调试信息：打印当前选座数量和已选座位列表
    printf("Order_Process: selected_seat_count = %d, selected_seats = '%s'\n", selected_seat_count, selected_seats);
    
    // 检查总票价是否为0（判断是否有至少一张选票的方式）
    int total_price = selected_seat_count * ticket_price;
    if(total_price == 0) {
        // 没有选座，显示错误消息并在1秒后自动隐藏加载面板
        show_loading_error("至少选择一张票后付款!");
        return;
    }
    
    // 正常流程：显示加载面板
    show_loading_panel();

    // 在写文件前，确保获取当前场次文本（防止 selected_time 为空）
    lv_dropdown_get_selected_str(ui_picktime, selected_time, sizeof(selected_time));

    time_t now    = time(NULL);
    struct tm * t = localtime(&now);

    // 生成取票码：第一个座位 + 日期（简单策略）
    char first_seat[16] = {0};
    if(sscanf(selected_seats, "%15s", first_seat) != 1) {
        strncpy(first_seat, "X", sizeof(first_seat) - 1);
    }

    char ticket_code_buf[32];
    if(t) {
        snprintf(ticket_code_buf, sizeof(ticket_code_buf), "%s%02d%02d%02d", first_seat, t->tm_year % 100,
                 t->tm_mon + 1, t->tm_mday);
    } else {
        snprintf(ticket_code_buf, sizeof(ticket_code_buf), "%s000000", first_seat);
    }

    // 写入订单文件（确保使用已获取的 selected_time）
    FILE * file = fopen(SEATS_FILE, "a");
    if(file) {
        fprintf(file, "用户:%s,日期:%d年%d月%d日,电影片名:%s,场次:%s,座位号:%s,取票码:%s\n", current_username,
                (t ? t->tm_year + 1900 : 1970), (t ? t->tm_mon + 1 : 1), (t ? t->tm_mday : 1), current_film_name,
                selected_time, selected_seats, ticket_code_buf);
        fclose(file);
    }

    // **重要**：ticket_code_buf 在栈上，不能直接传入定时器 user_data。改为 strdup，然后在回调中 free。
    char * ticket_heap = strdup(ticket_code_buf);
    if(ticket_heap == NULL) ticket_heap = strdup("ERR"); // 保底

    // 设置为3秒延迟，符合用户需求
    lv_timer_t * timer = lv_timer_create(order_process_timer, 3000, ticket_heap);
    lv_timer_set_repeat_count(timer, 1);
}

// ---------------- 取票检查 ----------------
void Check_Ticket_Code(lv_event_t * e)
{
    const char * ticket_code = lv_textarea_get_text(ui_TAKEnumin);
    if(ticket_code == NULL) ticket_code = "";

    if(strlen(ticket_code) == 0) {
        show_ticket_error("取票码不能为空");
        return;
    }

    if(!file_exists(SEATS_FILE)) {
        show_ticket_error("票务数据文件不存在");
        return;
    }

    FILE * file = fopen(SEATS_FILE, "r");
    if(!file) {
        show_ticket_error("票务数据文件无法打开");
        return;
    }

    char line[512];
    int found = 0;
    int valid = 0;

    while(fgets(line, sizeof(line), file)) {
        if(strstr(line, ticket_code)) {
            found = 1;

            // 检查用户名是否匹配
            char user_in_file[50] = {0};
            if(sscanf(line, "用户:%49[^,]", user_in_file) == 1) {
                trim_string(user_in_file);
                if(strcmp(user_in_file, current_username) == 0) {
                    valid = 1;
                    break;
                }
            }
        }
    }
    fclose(file);

    if(!found) {
        show_ticket_error("取票码错误,忘记找管理员");
    } else if(!valid) {
        show_ticket_error("取票码与当前用户不匹配");
    } else {
        show_ticket_success("取票口已出票");
    }
}

// ---------------- 弹窗与回调实现 ----------------
// 显示加载面板错误消息并在1秒后自动隐藏
static void show_loading_error(const char * message)
{
    if(ui_blackpanel) {
        // 设置为模态对话框，阻止其他操作
        lv_obj_clear_flag(ui_blackpanel, LV_OBJ_FLAG_HIDDEN);
        
        // 设置面板为可点击，阻止事件穿透到下层控件
        lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_CLICKABLE);
        lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_CLICK_FOCUSABLE);
        
        // 设置面板背景为半透明黑色，覆盖整个屏幕
        lv_obj_set_size(ui_blackpanel, LV_PCT(100), LV_PCT(100));
        lv_obj_center(ui_blackpanel);
        lv_obj_set_style_bg_color(ui_blackpanel, lv_color_black(), LV_PART_MAIN);
        lv_obj_set_style_bg_opa(ui_blackpanel, LV_OPA_70, LV_PART_MAIN);  // 70%透明度
        
        // 确保加载面板在最上层
        lv_obj_move_foreground(ui_blackpanel);
        
        // 检查是否有提示标签，如果有则设置消息
        if(ui_tip) {
            lv_label_set_text(ui_tip, message);
        }
        
        // 1秒后自动隐藏加载面板
        lv_timer_t * timer = lv_timer_create(hide_popup_timer, 1000, ui_blackpanel);
        lv_timer_set_repeat_count(timer, 1);
    }
}

static void show_ticket_error(const char * message)
{
    lv_obj_clear_flag(ui_CtakePopup, LV_OBJ_FLAG_HIDDEN);
    lv_label_set_text(ui_cwarntext, message);
    lv_timer_t * timer = lv_timer_create(hide_popup_timer, 1000, ui_CtakePopup);
    lv_timer_set_repeat_count(timer, 1);
}

static void show_ticket_success(const char * message)
{
    lv_obj_clear_flag(ui_CtakePopup, LV_OBJ_FLAG_HIDDEN);
    lv_label_set_text(ui_cwarntext, message);
    lv_timer_t * timer = lv_timer_create(ticket_success_timer, 3000, NULL);
    lv_timer_set_repeat_count(timer, 1);
}

static void hide_popup_timer(lv_timer_t * timer)
{
    if(timer == NULL) return;
    lv_obj_t * popup = (lv_obj_t *)timer->user_data;
    if(popup) {
        lv_obj_add_flag(popup, LV_OBJ_FLAG_HIDDEN);
        
        // 如果是加载面板，清除模态对话框标志
        if(popup == ui_blackpanel) {
            lv_obj_clear_flag(popup, LV_OBJ_FLAG_CLICKABLE);
            lv_obj_clear_flag(popup, LV_OBJ_FLAG_CLICK_FOCUSABLE);
        }
    }
    lv_timer_del(timer);
}

static void login_success_timer(lv_timer_t * timer)
{
    (void)timer;
    _ui_screen_change(&ui_TICKETING, LV_SCR_LOAD_ANIM_FADE_ON, 500, 500, &ui_TICKETING_screen_init);
}

static void register_success_timer(lv_timer_t * timer)
{
    (void)timer;
    _ui_screen_change(&ui_BEGIN, LV_SCR_LOAD_ANIM_FADE_ON, 500, 500, &ui_BEGIN_screen_init);
}

static void order_process_timer(lv_timer_t * timer)
{
    if(timer == NULL) return;
    char * ticket_code = (char *)timer->user_data;
    if(ticket_code && ticket_code[0] != '\0') {
        // 不再隐藏加载窗口，让它一直显示直到用户点击关闭
        // lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_HIDDEN);
        
        // 显示取票码窗口（作为加载窗口的子控件）
        lv_obj_clear_flag(ui_blackpaneltrue, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_qupiaoma, ticket_code);
    } else {
        // 异常情况：没有票号
        // 不再隐藏加载窗口，让它一直显示直到用户点击关闭
        // lv_obj_add_flag(ui_blackpanel, LV_OBJ_FLAG_HIDDEN);
        
        // 显示取票码窗口（作为加载窗口的子控件）
        lv_obj_clear_flag(ui_blackpaneltrue, LV_OBJ_FLAG_HIDDEN);
        lv_label_set_text(ui_qupiaoma, "ERROR");
    }
    // 完成后释放堆上 ticket_code 并删除定时器
    if(ticket_code) free(ticket_code);
    lv_timer_del(timer);

    // 重置选座（如果需要）
    reset_seat_selection();
}

static void ticket_success_timer(lv_timer_t * timer)
{
    (void)timer;
    lv_obj_add_flag(ui_CtakePopup, LV_OBJ_FLAG_HIDDEN);
    _ui_screen_change(&ui_TICKETING, LV_SCR_LOAD_ANIM_FADE_ON, 500, 500, &ui_TICKETING_screen_init);
}

// ---------------- 重置选座：把常见命名的复选框清除选中状态 ----------------
// 检查并更新已售出座位的状态
void check_and_update_occupied_seats(void)
{
    // 确保先初始化座位复选框数组
    init_seat_checkboxes();
    
    // 确保先获取当前场次
    if (ui_picktime) {
        lv_dropdown_get_selected_str(ui_picktime, selected_time, sizeof(selected_time));
    }
    
    // 重置所有座位状态（先设置为可选和默认样式）
    for (int i = 0; i < MAX_SEATS; i++) {
        if (seat_checkboxes[i]) {
            lv_obj_add_flag(seat_checkboxes[i], LV_OBJ_FLAG_CLICKABLE);
            // 重置为默认颜色（蓝色文本）
            lv_obj_set_style_text_color(seat_checkboxes[i], lv_color_hex(0x0000FF), LV_PART_MAIN | LV_STATE_DEFAULT);
        }
    }
    
    // 检查每个座位是否已被售出
    for (int i = 0; i < MAX_SEATS; i++) {
        if (seat_checkboxes[i] && is_seat_occupied(seat_names[i])) {
            // 座位已售出，设置为不可选
            lv_obj_clear_flag(seat_checkboxes[i], LV_OBJ_FLAG_CLICKABLE);
            // 确保已售出的座位显示为未选中状态
            lv_obj_clear_state(seat_checkboxes[i], LV_STATE_CHECKED);
            // 设置为灰色文本，使已售出的座位可视化
            lv_obj_set_style_text_color(seat_checkboxes[i], lv_color_hex(0x808080), LV_PART_MAIN | LV_STATE_DEFAULT);
        }
    }
}

// 场次切换事件处理函数
void on_time_change(lv_event_t * e)
{
    if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) {
        // 获取新选择的场次
        lv_dropdown_get_selected_str(ui_picktime, selected_time, sizeof(selected_time));
        
        // 重新检查已售出座位
        check_and_update_occupied_seats();
        
        // 只重置座位选择，不重置场次选择
        selected_seat_count = 0;
        selected_seats[0]   = '\0';
        
        // 清除所有座位复选框的选中状态
        for (int i = 0; i < MAX_SEATS; i++) {
            if (seat_checkboxes[i] && lv_obj_has_flag(seat_checkboxes[i], LV_OBJ_FLAG_CLICKABLE)) {
                lv_obj_clear_state(seat_checkboxes[i], LV_STATE_CHECKED);
            }
        }
        
        // 更新显示
        if (ui_postion) {
            lv_label_set_text_fmt(ui_postion, "座位号: %s", selected_seats);
        }
        
        if (ui_money) {
            int total_price = selected_seat_count * ticket_price;
            lv_label_set_text_fmt(ui_money, "票价(%d元/张): 总计%d元", ticket_price, total_price);
        }
    }
}

void reset_seat_selection(void)
{
    // 确保先初始化座位复选框数组
    init_seat_checkboxes();
    
    selected_seat_count = 0;
    selected_seats[0]   = '\0';
    
    // 强制重置场次选择为第一个选项（9:00），解决隐私泄露问题
    if(ui_picktime) {
        lv_dropdown_set_selected(ui_picktime, 0);
        lv_dropdown_get_selected_str(ui_picktime, selected_time, sizeof(selected_time));
    }
    
    // 清除所有座位复选框的选中状态
    for (int i = 0; i < MAX_SEATS; i++) {
        if (seat_checkboxes[i] && lv_obj_has_flag(seat_checkboxes[i], LV_OBJ_FLAG_CLICKABLE)) {
            lv_obj_clear_state(seat_checkboxes[i], LV_STATE_CHECKED);
        }
    }
    
    // 强制更新显示
    if (ui_postion) {
        lv_label_set_text_fmt(ui_postion, "座位号: %s", selected_seats);
    }
    
    if (ui_money) {
        int total_price = selected_seat_count * ticket_price;
        lv_label_set_text_fmt(ui_money, "票价(%d元/张): 总计%d元", ticket_price, total_price);
    }
}